VueCharts简化属性项的传递
概述
本节优化 vue-echarts 组件的封装,通过扩展 type(图表类型)和 component(组件类型)属性简化配置项传递,支持服务端动态返回的图表配置渲染。
问题分析
全量导入的体积问题
中后台系统中,服务端可能返回任意类型的图表配置,需要全量导入 ECharts 模块:
// 全量导入:包含所有图表类型,包体积较大
import * as echarts from 'echarts'
typescript
| 导入方式 | 包体积影响 | 适用场景 |
|---|---|---|
| 按需导入 | 小(~100-200KB) | 已知图表类型的页面 |
| 全量导入 | 大(~800KB+) | 服务端动态配置场景 |
属性简化方案
新增 Props 设计
// types.ts
export type ChartType =
| 'bar' | 'line' | 'pie' | 'scatter'
| 'radar' | 'map' | 'tree' | 'treemap'
| 'sunburst' | 'graph' | 'funnel' | 'gauge'
| 'boxplot' | 'heatmap' | 'parallel' | 'sankey'
export interface VEChartsProps {
/** ECharts option 配置 */
option?: Record<string, any>
/** 图表类型(简化配置用) */
type?: ChartType
/** 组件类型 */
component?: string
/** 主题 */
theme?: string | object
/** 初始化选项 */
initOptions?: Record<string, any>
/** 是否自动 resize */
autoresize?: boolean | { throttle: number }
/** 是否显示 loading */
loading?: boolean
/** 宽度 */
width?: string
/** 高度 */
height?: string
}
typescript
封装 VECharts 组件
<template>
<v-chart
class="ve-charts"
:option="mergedOption"
:theme="theme"
:init-options="initOptions"
:autoresize="autoresize"
:loading="loading"
:style="{ width, height }"
/>
</template>
<script setup lang="ts">
import { computed, provide } from 'vue'
import VChart from 'vue-echarts'
import { THEME_KEY } from 'vue-echarts'
import type { VEChartsProps } from './types'
const props = withDefaults(defineProps<VEChartsProps>(), {
autoresize: true,
loading: false,
width: '100%',
height: '400px'
})
// 提供主题
provide(THEME_KEY, props.theme)
// 合并 option:用户传入的 option 优先
const mergedOption = computed(() => {
if (props.option) return props.option
// 如果只传了 type,生成默认 option
if (props.type) {
return {
series: [{
type: props.type,
data: []
}]
}
}
return {}
})
</script>
<style scoped>
.ve-charts {
width: v-bind(width);
height: v-bind(height);
}
</style>
vue
使用方式对比
方式一:传完整 option(原方式)
<template>
<VECharts :option="barOption" height="300px" />
</template>
<script setup>
const barOption = {
title: { text: '销售统计' },
xAxis: { type: 'category', data: ['A', 'B', 'C'] },
yAxis: { type: 'value' },
series: [{ type: 'bar', data: [120, 200, 150] }]
}
</script>
vue
方式二:只传 type(简化方式)
<template>
<VECharts type="bar" :option="miniOption" />
</template>
vue
方式三:服务端动态配置
<template>
<!-- 服务端返回完整 option,直接渲染 -->
<VECharts :option="serverChartConfig" />
</template>
<script setup>
import { ref, onMounted } from 'vue'
const serverChartConfig = ref({})
onMounted(async () => {
const res = await fetch('/api/dashboard/charts')
serverChartConfig.value = await res.json()
// 服务端返回的 JSON 直接作为 ECharts option 使用
})
</script>
vue
全量导入 ECharts 模块
// utils/echarts-full.ts - 中后台系统使用
import { use } from 'echarts/core'
import * as echarts from 'echarts/core'
import { CanvasRenderer } from 'echarts/renderers'
import {
BarChart, LineChart, PieChart, ScatterChart,
RadarChart, MapChart, TreeChart, TreemapChart,
SunburstChart, GraphChart, FunnelChart, GaugeChart,
BoxplotChart, HeatmapChart, ParallelChart, SankeyChart
} from 'echarts/charts'
import {
TitleComponent, TooltipComponent, LegendComponent,
GridComponent, DatasetComponent, TransformComponent,
ToolboxComponent, DataZoomComponent, VisualMapComponent,
GraphicComponent, MarkLineComponent, MarkPointComponent
} from 'echarts/components'
use([
CanvasRenderer,
// 注册所有图表类型
BarChart, LineChart, PieChart, ScatterChart,
RadarChart, MapChart, TreeChart, TreemapChart,
SunburstChart, GraphChart, FunnelChart, GaugeChart,
BoxplotChart, HeatmapChart, ParallelChart, SankeyChart,
// 注册所有组件
TitleComponent, TooltipComponent, LegendComponent,
GridComponent, DatasetComponent, TransformComponent,
ToolboxComponent, DataZoomComponent, VisualMapComponent,
GraphicComponent, MarkLineComponent, MarkPointComponent
])
export default echarts
typescript
打包优化建议
| 策略 | 说明 | 效果 |
|---|---|---|
| 按需导入 | 只注册使用的图表类型 | 包体积减少 60-80% |
| CDN 外置 | echarts 通过 CDN 加载 | 主包体积显著减小 |
| 异步加载 | 路由级别动态 import | 首屏不加载图表代码 |
| 分模式打包 | 开发全量、生产按需 | 兼顾开发体验和性能 |
小结
- 通过
type属性简化图表配置,适用于简单场景 - 服务端动态配置场景需要全量导入 ECharts 模块
vue-echarts的optionprop 支持响应式更新,可直接绑定服务端数据- 全量导入会增加包体积,生产环境建议通过 CDN 外置或按需加载优化
↑